package com.example.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.Category;
import com.example.entity.Category;
import com.example.exception.CustomException;
import com.example.mapper.CategoryMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 资产分类业务处理
 **/
@Slf4j
@Service
public class CategoryService extends ServiceImpl<CategoryMapper, Category> implements IService<Category> {

    @Resource
    private CategoryMapper categoryMapper;

    /**
     * 新增
     */
    public void add(Category category) {
        if (category.getPid() == null || category.getPid() == 0) {
            category.setPid(0);
        } else {
            Category parent = categoryMapper.selectById(category.getPid());
            if (parent == null) {
                throw new CustomException("上级分类不存在");
            }
        }
        categoryMapper.insert(category);
    }

    /**
     * 删除
     */
    public void deleteById(Integer id) {
        categoryMapper.deleteById(id);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            categoryMapper.deleteById(id);
        }
    }

    /**
     * 修改
     */
    public void updateByIdWithCheck(Category category) {
        if (category.getPid().equals(category.getId())) {
            throw new CustomException("400","上级分类不能是自己");
        }
        Category parent = categoryMapper.selectById(category.getPid());
        List<Category> children = categoryMapper.selectByPid(category.getId());
        children.forEach(child -> {
            if (child.getId().equals(parent.getId())) {
                throw new CustomException("400", "上级分类不能是自己的子分类");
            }
        });
        categoryMapper.updateById(category);
    }

    /**
     * 根据ID查询
     */
    public Category selectById(Integer id) {
        return categoryMapper.selectById(id);
    }

    /**
     * 查询所有
     */
    public List<Category> selectAll(Category category) {
        return categoryMapper.selectAll(category);
    }

    /**
     * 分页查询
     */
    public PageInfo<Category> selectPage(Category category, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
//        List<Category> rootList = categoryMapper.selectByPid(0);
        List<Category> rootList = lambdaQuery()
                .eq(Category::getPid, 0)
                .like(StrUtil.isNotBlank(category.getName()),
                        Category::getName, category.getName())
                .list();

        // 直接复用
        Map<Integer, List<Category>> parentMap = buildParentMap();
        rootList.forEach(r -> r.setChildren(buildTree(parentMap, r.getId())));

        return PageInfo.of(rootList);
    }

    public List<Category> selectTree() {
        return buildTree(buildParentMap(), 0);
    }

    /**
     * 一次性查询全表并分组为 父→孩子 映射
     */
    private Map<Integer, List<Category>> buildParentMap() {
        PageHelper.clearPage(); // 防止被外层分页污染
        List<Category> all = categoryMapper.selectAll(null);
        if (CollUtil.isEmpty(all)) {
            return Collections.emptyMap();
        }
        return all.stream()
                .collect(Collectors.groupingBy(c -> Optional.ofNullable(c.getPid()).orElse(0)));
    }
    /**
     * 递归构建任意深度树
     *
     * @param parentMap 父→孩子映射
     * @param pid       当前要挂载的父id（从根 0 开始）
     */
    private List<Category> buildTree(Map<Integer, List<Category>> parentMap, Integer pid) {
        // 拿到当前父节点的所有孩子
        List<Category> children = parentMap.getOrDefault(pid, Collections.emptyList());
        for (Category child : children) {
            // 递归给每个孩子再找它的孩子
            child.setChildren(buildTree(parentMap, child.getId()));
        }
        return children;
    }

}